`timescale 1ns / 1ns
`include "../include/cpu_defines.sv"

module CPUCore(
    input   logic                       clk,
    input   logic                       resetn,
	input   logic [5: 0]                ext_int,
    
	output  logic                       inst_req,
	output 	logic 						inst_clear,
	output  logic                       inst_wr,
	output  logic [1: 0]                inst_size,
	(*mark_debug = "true"*)
	output  logic [31: 0]               inst_addr,

	output  logic [31: 0]               inst_wdata,
	(*mark_debug = "true"*)
	input   logic [1: 0][31: 0]         inst_rdata,
	input   logic [1: 0]                inst_rdata_valid,
	(*mark_debug = "true"*)
	input   logic [1: 0][31: 0] 		inst_request_addr,
	(*mark_debug = "true"*)
	input 	logic 						inst_tlb_invalid,
	(*mark_debug = "true"*)
	input 	logic 						inst_tlb_refill,	
	
`ifdef CPU_DEBUG
	output logic[31: 0]           	debug_retire1_pc,
	output logic [3: 0]           	debug_retire1_rf_wen,
	output logic [4: 0] 		  	debug_retire1_rf_wnum,
	output logic [31: 0]          	debug_retire1_rf_wdata,
	output logic [31: 0] 			debug_retire2_pc,
	output logic [3: 0] 			debug_retire2_rf_wen,
	output logic [4: 0] 			debug_retire2_rf_wnum,
	output logic [31: 0] 			debug_retire2_rf_wdata,
	output logic [31: 0]			debug_cp0_random,
	output logic [31: 0] 			debug_cp0_cause,
	output logic [31: 0]			debug_cp0_count,
	output logic 					debug_int,
	output logic 					debug_commit1,
	output logic 					debug_commit2,
	output logic 					predict_en,
	output logic 					predict_err_en,
`endif 

	input   logic                       inst_addr_ok,
	(*mark_debug = "true"*)
	input   logic                       inst_data_ok,
	input 	logic 						inst_conflict,
	// input 	logic 						inst_accept,
	input 	logic 						data_success,
	// input 	logic 						clear_accept,
	output  logic                       data_req,
	output 	logic 						data_write_req,
	input 	logic 						data_write_accept,
	output 	logic 						data_clear,
	output 	logic 						data_abandon_lookup,
	output 	logic [3: 0]				data_wstrb,
	output 	logic [3: 0]				data_rwstrb,
	output  logic [31: 0]               data_addr,
	output 	logic [31: 0]				data_waddr,
	output  logic [31: 0]               data_wdata,
	output	logic [`READ_BUFFER_WIDTH-1: 0]	data_issue_queue_index,
	output	logic						data_enable_miss,
	output 	logic [19: 0]				data_write_ptag,
	output 	logic [19: 0] 				vwtag,
	input 	logic [19: 0]				pwtag,
	input 	logic [19: 0]				prtag,
	input 	logic 						data_runcache,
	input 	logic 						data_wuncache,
	input 	logic 						rdata_tlb_invalid,
	input 	logic 						rdata_tlb_refill,
	input 	logic 						wdata_tlb_refill,
	input 	logic 						wdata_tlb_invalid,
	input 	logic 						data_tlb_modify,
	input   logic [31: 0]               data_rdata,
	input 	logic [`READ_BUFFER_WIDTH-1: 0]				read_queue_index,
	input 	logic 						mshr_data_ok,
	input 	logic [`READ_BUFFER_WIDTH-1: 0]				mshr_queue_index,
	input 	logic [31: 0]				mshr_data,
	input   logic                       data_addr_ok,
	input   logic                       data_data_ok,
	input 	logic 						data_waddr_ok,
	input 	logic 						data_uncache_ok, // uncache buffer可以接受数据
	input 	logic 						data_enable_miss_back,

	output 	logic 						uncache_req,
	output 	logic 						uncache_wr,
	output 	logic [3: 0]				uncache_wstrb,
	output 	logic [31: 0]				uncache_addr,
	output 	logic [`READ_BUFFER_WIDTH-1: 0] uncache_queue_index,
	output 	logic [31: 0]				uncache_data,
	input 	logic 						uncache_data_ok, // uncache buffer数据返回,但是他的数据是从mshr_data端口返回的

	input 	logic 						icache_ready,
	input 	logic 						dcache_ready,
	output 	logic 						cache_valid,
	output 	logic [4: 0]				cacheop,
	output 	logic [31: 0]				cache_addr,

    input 	logic [31:0] 				tlb_entry_lo0_in,
    input 	logic [31:0] 				tlb_entry_lo1_in,
    input 	logic [31:0] 				tlb_page_mask_in,
    input 	logic [31:0] 				tlb_entry_hi_in,
    input 	logic [31:0] 				tlb_index_in,
	input  	logic						tlb_tlbp_find,
	output	logic [3: 0]				cp0_tlb_type,
	output 	logic 						cp0_tlb_inst_en,
	
	output	logic [31:0]				cp0_entry_hi_out, 
	output	logic [31:0]				cp0_page_mask_out,
	output	logic [31:0]				cp0_entry_lo0_out,
	output	logic [31:0]				cp0_entry_lo1_out,
	output	logic [31:0]				cp0_index_out,
	output	logic [31:0]				cp0_random_out,
	output 	logic [31: 0]				cp0_taglo_out,
	output 	logic 						kseg0_uncache
    );
    
    assign inst_wr = 0;
	assign inst_wdata = 32'b0;
    // remember: all reg have two variable: ready and clear 
    // ready is 0 means we need to hold all varaibles keep it's value 
    // clear means all varaibles set as default 
	//  example: see PC_reg
    
    // remember2: all modules must have a meaningful name
	(* keep="true" *)
	logic clear_bus_front;
	(* keep="true" *)
	logic clear_bus_prf;
	(* keep="true" *)
	logic clear_bus_issue;
	(* keep="true" *)
	logic clear_bus_wb;
	logic clear_bus;
// IF
	logic predict_conflict1, predict_conflict2, predict_clear, predict_clear_next;
	logic branch_fail_flush;
	logic instBuffer_flush_next;
	logic branch_inst2_selector;
	logic next_inst2_clear;
	logic [`BRANCH_BUFFER_WIDTH-1: 0] branch_index;
	logic[`STAGE_SIZE-1: 0] ready, clear;

	logic instBuffer_count_ok;
	logic 						instBuffer_inst1en;
	logic 						instBuffer_inst2en;
    logic [`INST_BUS]            instBuffer_inst1;
    logic [`INST_BUS]            instBuffer_inst2;
    logic [`INST_ADDR_BUS]       instBuffer_iaddr1;
    logic [`INST_ADDR_BUS]       instBuffer_iaddr2;
	logic instBuffer_tlb_refill1, instBuffer_tlb_refill2;
	logic instBuffer_tlb_invalid1, instBuffer_tlb_invalid2;
	// logic discard_inst2;

    logic                        instBuffer_ok;
	logic[1: 0] issue_mode, request_num;
	logic [`EXC_CODE_BUS] if_inst1_exccode;
	logic [`EXC_CODE_BUS] if_inst2_exccode;

// ID
	logic [1: 0] id_clear;
	logic [5: 0] id_inst1_rs, id_inst1_rt, id_dcu_inst1_rs, id_dcu_inst1_rt;
	logic [5: 0] id_inst1_rd;
	logic [31: 0] id_inst1_src1, id_inst1_src2, id_inst_addr, id_analyze_addr;
	logic [`INST_TYPE_BUS] id_inst1_type;
	logic [`ALUOP_BUS] id_inst1_aluop;
	logic id_inst1_multdiv;
	logic [5: 0] id_inst2_rs, id_inst2_rt;
	logic [5: 0] id_inst2_rd;
	logic [31: 0] id_inst2_src1, id_inst2_src2;
	logic [`INST_TYPE_BUS] id_inst2_type;
	logic [`ALUOP_BUS] id_inst2_aluop;
	logic id_inst2_multdiv;
	logic [`MULTOP_BUS] id_inst1_multop, id_inst2_multop;
	logic id_inst1_place2, id_inst2_place2;
	logic id_inst1_madd, id_inst2_madd;
	logic id_inst1_mul, id_inst2_mul;
	logic [`CP0OP_BUS] id_inst1_cp0op, id_inst2_cp0op;
	logic id_inst1_exception, id_inst2_exception;
	logic id_inst1_mult, id_inst2_mult, id_inst1_multsigned, id_inst2_multsigned;
	logic id_inst1_branch, id_inst2_branch, id_dcu_inst2_branch;
	logic id_inst1_rasup, id_inst2_rasup, id_inst1_rasdown, id_inst2_rasdown, id_dcu_inst2_rasup, id_dcu_inst2_rasdown;
	logic [`MEMOP_BUS] id_inst1_memop, id_inst2_memop;

	logic [5: 0] id_dcu_inst2_rs, id_dcu_inst2_rt, id_dcu_inst2_rd;
	logic [`INST_TYPE_BUS] id_dcu_inst2_type;
	logic [`ALUOP_BUS] id_dcu_inst2_aluop;
	logic id_inst1_en, id_inst2_en;
	logic id_inst1_j ,id_inst2_j;
	logic [`EXC_CODE_BUS] id_inst1_exccode;
	logic [`EXC_CODE_BUS] id_inst2_exccode, id_dcu_inst2_exccode;

	`ifdef CPU_DEBUG
		logic [31:0] debug_idrat_inst1_out;
		logic [31:0] debug_idrat_inst2_out;
		logic [31:0] debug_idrat_addr1_out;
		logic [31:0] debug_idrat_addr2_out;
		logic [31:0] debug_ratdis_inst1_out;
		logic [31:0] debug_ratdis_inst2_out;
	`endif

// RAT
	logic rat_inst1_en, rat_inst2_en, rat_inst2_en_in;
	// (* MAX_FANOUT=300 *)
	logic [5: 0] rat_inst1_rs, rat_inst1_rt;
	// (* MAX_FANOUT=300 *)
	logic [5: 0] rat_inst1_rd;
	logic [31: 0] rat_inst1_src1, rat_inst1_src2, rat_inst_addr1, rat_inst_addr2, rat_analyze_addr;
	logic [`INST_TYPE_BUS] rat_inst1_type;
	logic [`ALUOP_BUS] rat_inst1_aluop;
	logic rat_inst1_store, rat_inst1_load, rat_inst2_store, rat_inst2_load;
	logic [1: 0] rat_inst1_memsize, rat_inst2_memsize;
	logic rat_inst1_memunsigned, rat_inst2_memunsigned;
	logic [5: 0] rat_inst2_rs_in, rat_inst2_rt_in, rat_inst2_rd_in;
	logic [`EXC_CODE_BUS] rat_inst1_exccode, rat_inst2_exccode;
	logic [`CP0OP_BUS] rat_inst1_cp0op, rat_inst2_cp0op;
	logic [`MULTOP_BUS] rat_inst1_multop, rat_inst2_multop;
	logic rat_inst1_branch, rat_inst2_branch;
	logic rat_inst1_rasup, rat_inst2_rasup, rat_inst1_rasdown, rat_inst2_rasdown;
	logic [`MEMOP_BUS] rat_inst1_memop, rat_inst2_memop;
	logic rat_inst1_place2, rat_inst2_place2;

	// (* MAX_FANOUT=300 *)
	logic [5: 0] rat_inst2_rs, rat_inst2_rt;
	// (* MAX_FANOUT=300 *)
	logic [5: 0] rat_inst2_rd;
	logic [31: 0] rat_inst2_src1, rat_inst2_src2;
	logic [`INST_TYPE_BUS] rat_inst2_type, rat_inst2_type_in;
	logic [`ALUOP_BUS] rat_inst2_aluop;

	logic rat_stall, rob_flush, rob_direction1, rob_direction2, rob_en1, rob_en2;
	logic [`INST_TYPE_BUS] rob_inst1_type, rob_inst2_type;
	logic retire_branch_fail1, retire_branch_fail2;
	logic next_branch_fail;
	logic rob_isds1, rob_isds2;
	logic [5: 0] rat_rob_index1, rat_rob_index2, rob_origin_rd1, rob_origin_rd2, rob_rd1, rob_rd2;
	logic [5: 0] wb_origin_rd1, wb_origin_rd2;
	logic [5: 0] rt_rob_index1, rt_rob_index2;
	logic [`EXC_CODE_BUS] rob_exccode1, rob_exccode2, rob_exccode;
	logic [5: 0] cp0_rob_index;
	logic [31: 0] rob_pc1, rob_pc2, rob_pc4, cp0_pc;
	logic rob_cp0_en1, rob_cp0_en2;
	logic ras_up1, ras_up2, rat_down1, rat_down2;
	logic rob_branchds1, rob_branchds2;
	logic rob_ll1, rob_ll2;
	logic rob_entryhi1, rob_entryhi2;
	logic rob_fetchexc1, rob_fetchexc2;
	logic ras_down1, ras_down2;
	logic stop_retire, out_rob_en1_pre, out_rob_en2_pre, out_rob_cp0_en1_pre, out_rob_cp0_en2_pre;

	logic [5: 0] prf_inst1_rs, prf_inst1_rt, prf_inst1_rd, prf_inst2_rs, prf_inst2_rt, prf_inst2_rd;
	logic prf_inst1_src1_en, prf_inst1_src2_en, prf_inst2_src1_en, prf_inst2_src2_en;
	logic prf_flush_request;
	logic prf_inst1_rs_ready, prf_inst1_rt_ready, prf_inst2_rs_ready, prf_inst2_rt_ready;
	logic [5: 0] mem_write_rs, mem_write_rt, mem_read_rs;
	logic [31: 0] mem_write_src1, mem_write_src2, mem_read_src1;
// DIS
	logic dis_inst1_rs_ready, dis_inst1_rt_ready, dis_inst2_rs_ready, dis_inst2_rt_ready;
	// logic [1: 0] dis_inst1_rs_select, dis_inst1_rt_select, dis_inst2_rs_select, dis_inst2_rt_select;
	// logic [31: 0] dis_rs1_data, dis_rs2_data, dis_rt1_data, dis_rt2_data;
	logic dis_rob_direction1, dis_rob_direction2;
	logic dis_inst1_en, dis_inst2_en;
	logic dis_inst1_branch, dis_inst2_branch;
	logic [5: 0] dis_inst1_origin_rs, dis_inst2_origin_rs;
	logic [5: 0] dis_inst1_rs_in, dis_inst1_rt_in, dis_inst1_rd, dis_inst2_rs_in, dis_inst2_rt_in, dis_inst2_rd;
	logic [5: 0] dis_inst1_rs, dis_inst1_rt, dis_inst2_rs, dis_inst2_rt;
	logic [5: 0] dis_rob_index1, dis_rob_index2;
	logic [31: 0] dis_analyze_addr;
	logic [31: 0] dis_inst1_src1_in, dis_inst1_src2_in, dis_inst2_src1_in, dis_inst2_src2_in;
	logic [31: 0] dis_inst1_src1, dis_inst1_src2, dis_inst2_src1, dis_inst2_src2;
	logic [`INST_TYPE_BUS] dis_inst1_type, dis_inst2_type;
	logic [`ALUOP_BUS] dis_inst1_aluop, dis_inst2_aluop;
	logic dis_inst1_store, dis_inst1_load, dis_inst2_store, dis_inst2_load;
	logic [1: 0] dis_inst1_memsize, dis_inst2_memsize;
	logic dis_inst1_memunsigned, dis_inst2_memunsigned;
	logic [`EXC_CODE_BUS] dis_inst1_exccode, dis_inst2_exccode;
	logic [`CP0OP_BUS] dis_inst1_cp0op, dis_inst2_cp0op;
	logic [`MULTOP_BUS] dis_inst1_multop, dis_inst2_multop;
	logic [`MEMOP_BUS] dis_inst1_memop, dis_inst2_memop;

	logic dis_alu_en1, dis_alu_en2;
	logic [5: 0] alu_inst1_rd, alu_inst2_rd;
	logic [31: 0] alu_inst1_src1, alu_inst1_src2, alu_inst2_src1, alu_inst2_src2;
	logic dis_alu_stall_request, alu_inst1_valid, alu_inst2_valid;
	logic [5: 0] alu_inst1_rob_index, alu_inst2_rob_index;
	logic [`ALUOP_BUS] alu_inst1_aluop, alu_inst2_aluop;
	logic alu_prf_en1, alu_prf_en2;
	logic [5: 0] alu_prf_rs1, alu_prf_rs2, alu_prf_rt1, alu_prf_rt2, alu_prf_rd1, alu_prf_rd2;
	logic [31: 0] alu_prf_src1, alu_prf_src2, alu_prf_src3, alu_prf_src4;
	logic out_alu1_valid, out_alu2_valid, out_alu1_conflict, out_alu2_conflict;
	logic [`EXC_CODE_BUS] alu_inst1_exccode, alu_inst2_exccode;
	logic [3: 0] alu_branch_index1, alu_branch_index2;
	logic alu_inst1_branch, alu_inst2_branch;

	logic dis_mult_en;
	logic mult_inst_valid;
	logic [`MULTOP_BUS] mult_inst_type;
	logic [5: 0] mult_inst_rd1;
	logic [5: 0] mult_inst_rd2;
	logic [31: 0] mult_inst_src1, mult_inst_src2, mult_inst_src3, mult_inst_src4;
	logic [31: 0] mult_inst_src1_unsign;
	logic [31: 0] mult_inst_src2_unsign;
	logic mult_inst_src1_issign;
	logic mult_inst_src2_issign;
	logic [5: 0] mult_inst_rob_index1;
	logic [5: 0] mult_inst_rob_index2;
	logic [5: 0] mult_prf_rs, mult_prf_rt;
	logic [31: 0] mult_prf_src1, mult_prf_src2;
	logic [`EXC_CODE_BUS] mult_inst_exccode;

	logic dis_mult_stall_request;

	logic dis_stall_req;

	logic dis_mem_en1, dis_mem_en2, mem_inst_wb_receive, mem_end, dis_mem_stall_req;
	logic [5: 0] mem_rd, mem_next_rd;
	logic [5: 0] mem_rob_index;
	logic [31: 0] mem_data;
	logic [`EXC_CODE_BUS] mem_exccode;
	logic [31: 0] mem_addr;
	logic vaddr_we, mem_entryhi_we;
	logic [5: 0] vaddr_rob_index;
	logic search4_en;
	logic [5: 0] mem_read_rt;
	// logic [31: 0] mem_read_src2;

	logic dis_cp0_en1, dis_cp0_en2;
	logic [31: 0] prf_cp0_data, cp0_rdata, cp0_wdata, cp0_wb_data;
	logic [`CP0OP_BUS] cp0_op;
	logic cp0_end, cp0_we, dis_cp0_stall_req, cp0_wb_receive;
	logic [5: 0] cp0_rd, cp0_wb_rd, prf_cp0_rt, cp0_wb_rob_index, cp0_next_rd;
	logic [`EXC_CODE_BUS] cp0_wb_exccode;
	logic [5: 0] cp0_rt;
	logic cp0_soft_int, cp0_we_inst;
	logic waiting;

// EXE

	logic [5: 0] exe_alu_inst1_rd, exe_alu_inst2_rd,
	exe_alu_inst1_rob_index, exe_alu_inst2_rob_index;
	logic [31: 0] exe_alu_inst1_ans, exe_alu_inst2_ans;
	logic exe_alu_inst1_end, exe_alu_inst2_end;
	logic alu_inst1_acceptable, alu_inst2_acceptable;
	logic alu_inst1_wb_receive, alu_inst2_wb_receive;
	logic wb_alu_branch1, wb_alu_branch2;
	logic [31: 0] alu_branch_ans1, alu_branch_ans2;
	logic [`BRANCH_BUFFER_WIDTH-1: 0] exe_alu_branch_index1, exe_alu_branch_index2;
	logic [5: 0] alu_next_rd1, alu_next_rd2;
	logic [`EXC_CODE_BUS] exe_alu_inst1_exccode, exe_alu_inst2_exccode;
	logic user_mode;

	//EXE_MULT FU
	logic [5: 0] mult_rd, mult_rob_index, mult_next_rd;
	logic [31: 0] mult_src;
	logic mult_inst_end;
	logic mult_inst_acceptable;
	logic mult_inst_wb_receive;
	logic [`EXC_CODE_BUS] mult_fu_exccode;
	// logic mult_unit_full;

// WB
	logic [2: 0] end_num;
	typedef struct packed{
		logic en;
		logic [2: 0] select;
		logic [2: 0] next_select;
		logic [5: 0] rd;
		logic [5: 0] rob_index;
		logic [31: 0] data;
		logic [`EXC_CODE_BUS] exccode;
	} CDBController_t;
//cp0 
	logic cp0_clear, cp0_retire_en, next_cp0_clear, next_cp0_clear_front;
	logic [31: 0] cp0_addr, next_cp0_addr, cp0_int_addr, rob_pc8, hard_int_addr;
	logic [31: 0] prev_int_addr;
	logic [2: 0] cp0_soft_en;
	logic int_ds, hard_int_ds;
	logic int_interrupt;

	CDBController_t cdb_controller[2: 0];
	logic cdb1_use, cdb2_use, cdb3_use;
	logic [5: 0] next_wb_rd1, next_wb_rd2, next_wb_rd3;

	BarrierController barrier_controller(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.inst_data_ok(inst_data_ok),
		.data_data_ok(data_data_ok),
		.inst_addr_ok(inst_addr_ok),
		.data_addr_ok(data_addr_ok),
		.inst_buffer_ok(instBuffer_ok),
		.rat_stall(rat_stall),
		.dis_stall(dis_stall_req),
		.predict_clear(predict_clear),
		.branch_predict_fail(predict_conflict1 || predict_conflict2),
		.branch_fail(rob_en1 && retire_branch_fail1 || rob_en2 && retire_branch_fail2),
		.ready(ready),
		.clear(clear),
		.flush(branch_fail_flush)
	);

	always_ff @(posedge clk)begin
		// branch_front_clear_next <= branch_front_clear;
		predict_clear_next <= predict_clear;
		next_cp0_clear_front <= cp0_clear;
		instBuffer_flush_next <= predict_clear;
		next_branch_fail <= branch_fail_flush;
		next_inst2_clear <= 1'b0;
		clear_bus_front <= predict_clear || cp0_clear;
		clear_bus_issue <= predict_clear || cp0_clear;
		clear_bus_prf <= predict_clear || cp0_clear;
		clear_bus_wb <= predict_clear || cp0_clear;
		clear_bus <= predict_clear || cp0_clear;
	end

	assign predict_clear = rob_en1 && retire_branch_fail1 || rob_en2 && retire_branch_fail2;
	FrontEnd front_end(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.cp0_fail(cp0_clear),
		.branch_fail(predict_clear),
		.use_branch_addr(rob_cp0_en1 && rob_exccode1 == `EXC_FLUSH && rob_isds1 || rob_cp0_en2 && rob_exccode2 == `EXC_FLUSH && rob_isds2),
		.btb_clear(rob_cp0_en1 && rob_fetchexc1 || rob_cp0_en2 && rob_fetchexc2),
		.stall(rat_stall || dis_stall_req),
		.inst_i(inst_rdata),
		.inst_valid_i(inst_rdata_valid),
		.inst_request_addr(inst_request_addr),
		.inst_addr_ok(inst_addr_ok),
		.inst_data_ok(inst_data_ok),
		// .inst_accept(inst_accept),
		.tlb_refill(inst_tlb_refill),
		.tlb_invalid(inst_tlb_invalid),
		.dis_branch_en(!dis_stall_req && (dis_inst1_en && dis_inst1_type == `INST_TYPE_BRANCH || dis_inst2_en && dis_inst2_type == `INST_TYPE_BRANCH)),
		.dis_j_en(!dis_stall_req && (dis_inst1_en && dis_inst1_branch || dis_inst2_en && dis_inst2_branch)), // 这个branch包含所有种类的跳转指令
		.dis_rob_index((dis_inst1_en && dis_inst1_branch ? dis_rob_index1[5: 1] : dis_rob_index2[5: 1])),
		.dis_analyze_addr(dis_analyze_addr),
		.wb_branch_en1(wb_alu_branch1),
		.wb_branch_en2(wb_alu_branch2),
		.wb_branch_index1(exe_alu_branch_index1),
		.wb_branch_index2(exe_alu_branch_index2),
		.wb_rob_index1(exe_alu_inst1_rob_index[5: 1]),
		.wb_rob_index2(exe_alu_inst2_rob_index[5: 1]),
		.wb_branch1(cdb_controller[0].select[0] ? alu_branch_ans1 : alu_branch_ans2),
		.wb_branch2(cdb_controller[1].select[0] ? alu_branch_ans1 : alu_branch_ans2),
		.branch_retire_rob_index(rob_isds1 ? rt_rob_index1 : rt_rob_index2),
		.branch_retire_en(rob_en1 && rob_branchds1 || rob_en2 && rob_branchds2),
		.retire_branch(rob_branchds1 || rob_branchds2),
		.cp0_addr(cp0_addr),
		.branch_index(branch_index),
		.branch_error1(predict_conflict1),
		.branch_error2(predict_conflict2),
		.inst_req(inst_req),
		.inst_size(inst_size),
		.inst_clear(inst_clear),
		.inst_addr(inst_addr),
		.ien_o({id_inst2_en, id_inst1_en}),
		.inst_o({instBuffer_inst2, instBuffer_inst1}),
		.iaddr_o({instBuffer_iaddr2, instBuffer_iaddr1}),
		.tlb_refill_o({instBuffer_tlb_refill2, instBuffer_tlb_refill1}),
		.tlb_invalid_o({instBuffer_tlb_invalid2, instBuffer_tlb_invalid1}),
		.issue_num(issue_mode),
		.ras_up({ras_up2, ras_up1}),
		.ras_down({ras_down2, ras_down1}),
		.analyze_addr(id_analyze_addr)
	);
	assign predict_en = rob_en1 && rob_branchds1 || rob_en2 && rob_branchds2;
	assign predict_err_en = rob_en1 && retire_branch_fail1 || rob_en2 && retire_branch_fail2;

	assign if_inst1_exccode = id_inst1_en && instBuffer_tlb_refill1 ? `EXC_RTLBL : id_inst1_en && instBuffer_tlb_invalid1 ? `EXC_ITLBL : id_inst1_en && instBuffer_iaddr1[1: 0] != 2'b00 || instBuffer_iaddr1[31] && user_mode ? `EXC_AdEL : `EXC_NONE;
	assign if_inst2_exccode = id_inst2_en && instBuffer_tlb_refill2 ? `EXC_RTLBL : id_inst2_en && instBuffer_tlb_invalid2 ? `EXC_ITLBL : id_inst2_en && instBuffer_iaddr2[1: 0] != 2'b00 || instBuffer_iaddr2[31] && user_mode ? `EXC_AdEL : `EXC_NONE;

    // ID
	DCU dcu1(
		.cpu_rst_n(resetn),
		.inst(id_inst1_en && instBuffer_iaddr1[1: 0] != 2'b00 ? 0 : instBuffer_inst1),
		.inst_addr(instBuffer_iaddr1),
		.id_id_exccode_in(if_inst1_exccode),
		.inst_rs(id_dcu_inst1_rs),
		.inst_rt(id_dcu_inst1_rt),
		.inst_rd(id_inst1_rd),
		.inst_src1(id_inst1_src1),
		.inst_src2(id_inst1_src2),
		.inst_type(id_inst1_type),
		.aluop(id_inst1_aluop),
		.multdiv(id_inst1_multdiv),
		.j_inst(id_inst1_j),
		.branch_inst(id_inst1_branch),
		.id_exccode(id_inst1_exccode),
		.cp0op(id_inst1_cp0op),
		.exception_type(id_inst1_exception),
		.rasup(id_inst1_rasup),
		.rasdown(id_inst1_rasdown),
		.memop(id_inst1_memop),
		.multop(id_inst1_multop),
		.place2(id_inst1_place2),
		.inst_madd(id_inst1_madd),
		.mul(id_inst1_mul)
	);

	DCU dcu2(
		.cpu_rst_n(resetn),
		.inst(id_inst1_en && instBuffer_iaddr1[1: 0] != 2'b00 ? 0 : instBuffer_inst2),
		.inst_addr(instBuffer_iaddr2),
		.id_id_exccode_in(if_inst2_exccode),
		.inst_rs(id_dcu_inst2_rs),
		.inst_rt(id_dcu_inst2_rt),
		.inst_rd(id_dcu_inst2_rd),
		.inst_src1(id_inst2_src1),
		.inst_src2(id_inst2_src2),
		.inst_type(id_dcu_inst2_type),
		.aluop(id_dcu_inst2_aluop),
		.multdiv(id_inst2_multdiv),
		.j_inst(id_inst2_j),
		.branch_inst(id_dcu_inst2_branch),
		.id_exccode(id_dcu_inst2_exccode),
		.cp0op(id_inst2_cp0op),
		.exception_type(id_inst2_exception),
		.rasup(id_dcu_inst2_rasup),
		.rasdown(id_dcu_inst2_rasdown),
		.memop(id_inst2_memop),
		.multop(id_inst2_multop),
		.place2(id_inst2_place2),
		.inst_madd(id_inst2_madd),
		.mul(id_inst2_mul)
	);
	// 如果是乘除法需要额外注意，因为乘除法的inst2_en是有效的，因此传递到rat时所有信号并不会清空
	assign id_inst1_rs = id_inst1_madd ? `REG_LO : id_dcu_inst1_rs;
	assign id_inst1_rt = id_inst1_madd ? `REG_HI : id_dcu_inst1_rt;
	assign id_inst2_rs = id_inst1_madd ? id_dcu_inst1_rs : id_inst1_place2 ? 0 : id_dcu_inst2_rs;
	assign id_inst2_rt = id_inst1_madd ? id_dcu_inst1_rt : id_inst1_place2 ? 0 : id_dcu_inst2_rt;
	assign id_inst2_rd = id_inst1_place2 && !id_inst1_mul ? `REG_LO : id_inst1_mul ? 0 : id_dcu_inst2_rd;
	assign id_inst2_aluop = id_inst1_place2 ? 0 : id_dcu_inst2_aluop;
	assign id_inst2_type = id_inst1_place2 ? `INST_TYPE_MULT : id_dcu_inst2_type;
	assign id_inst2_exccode = id_inst1_place2? `EXC_NONE : id_dcu_inst2_exccode;
	assign id_inst2_branch = id_inst1_place2 ? 1'b0 : id_dcu_inst2_branch;
	assign id_inst2_rasup = id_inst1_place2 ? 1'b0 : id_dcu_inst2_rasup;
	assign id_inst2_rasdown = id_inst1_place2 ? 1'b0 : id_dcu_inst2_rasdown;
	assign id_inst_addr = id_inst1_en ? instBuffer_iaddr1 : instBuffer_iaddr2;
// RAT
	assign id_clear[0] = ~resetn | clear_bus_front;
	assign id_clear[1] = ~resetn | clear_bus_front;
	`IDRAT_REG_DEFINE(1)
	`IDRAT_REG_DEFINE(2)
	assign rat_inst2_en_in = ~next_inst2_clear & rat_inst2_en;
	assign rat_inst2_type_in = {3{~next_inst2_clear}} & rat_inst2_type;
	assign rat_inst2_rs_in = {6{~next_inst2_clear}} & rat_inst2_rs;
	assign rat_inst2_rt_in = {6{~next_inst2_clear}} & rat_inst2_rt;
	assign rat_inst2_rd_in = {6{~next_inst2_clear}} & rat_inst2_rd;
	always_ff @(posedge clk)begin
		if(~dis_stall_req & ~rat_stall)begin
			rat_inst_addr1 <= instBuffer_iaddr1;
			rat_inst_addr2 <= issue_mode[1] ? instBuffer_iaddr2 : instBuffer_iaddr1;
			rat_analyze_addr <= id_analyze_addr;
		end
	end


	PRF prf(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.stall(rat_stall || dis_stall_req),
		.inst1_en(rat_inst1_en),
		.inst2_en(rat_inst2_en_in),
		.inst1_rs(rat_inst1_rs),
		.inst1_rt(rat_inst1_rt),
		.inst1_rd(rat_inst1_rd),
		.inst2_rs(rat_inst2_rs_in),
		.inst2_rt(rat_inst2_rt_in),
		.inst2_rd(rat_inst2_rd_in),
		.rob_en1(rob_en1),
		.rob_en2(rob_en2),
		.rob_origin_rd1(rob_origin_rd1),
		.rob_origin_rd2(rob_origin_rd2),
		.rob_rd1(rob_rd1),
		.rob_rd2(rob_rd2),
		.wb_en1((cdb_controller[0].en)),
		.wb_en2((cdb_controller[1].en)),
		.wb_en3(cdb_controller[2].en),
		.wb_rd1(cdb_controller[0].rd),
		.wb_rd2(cdb_controller[1].rd),
		.wb_rd3(cdb_controller[2].rd),
		.wb_data1(cdb_controller[0].data),
		.wb_data2(cdb_controller[1].data),
		.wb_data3(cdb_controller[2].data),
		.branch_fail1(rob_en1 && retire_branch_fail1 || rob_cp0_en1 || int_interrupt),
		.branch_fail2(rob_en2 && retire_branch_fail2 || rob_cp0_en2),
		.out_inst1_rs(prf_inst1_rs),
		.out_inst1_rt(prf_inst1_rt),
		.out_inst1_rd(prf_inst1_rd),
		.out_inst2_rs(prf_inst2_rs),
		.out_inst2_rt(prf_inst2_rt),
		.out_inst2_rd(prf_inst2_rd),
		.inst1_src1_en(prf_inst1_src1_en),
		.inst1_src2_en(prf_inst1_src2_en),
		.inst2_src1_en(prf_inst2_src1_en),
		.inst2_src2_en(prf_inst2_src2_en),
		.flush_request(prf_flush_request),
		.search1(mem_write_rs),
		.search2(mem_write_rt),
		.search3(mem_read_rs),
		.alu_rs1(alu_prf_rs1),
		.alu_rs2(alu_prf_rs2),
		.alu_rt1(alu_prf_rt1),
		.alu_rt2(alu_prf_rt2),
		.mult_rs(mult_prf_rs),
		.mult_rt(mult_prf_rt),
		.cp0_rt(search4_en ? mem_read_rt : prf_cp0_rt),

		.out_data1(mem_write_src1),
		.out_data2(mem_write_src2),
		.out_data3(mem_read_src1),
		.alu_src1(alu_prf_src1),
		.alu_src2(alu_prf_src2),
		.alu_src3(alu_prf_src3),
		.alu_src4(alu_prf_src4),
		.mult_src1(mult_prf_src1),
		.mult_src2(mult_prf_src2),
		.cp0_data(prf_cp0_data)
	);

	ROB rob(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.stall(rat_stall || dis_stall_req),
		.clear(clear_bus_prf),
		.inst1_en(rat_inst1_en),
		.inst2_en(rat_inst2_en_in),
		.inst1_branch(rat_inst1_branch),
		.inst2_branch(rat_inst2_branch),
		.inst_addr1(rat_inst_addr1),
		.inst_addr2(rat_inst_addr2),
		.inst1_type(rat_inst1_type),
		.inst2_type(rat_inst2_type_in),
		.inst1_rd(rat_inst1_rd),
		.prf_inst1_rd(prf_inst1_rd),
		.inst2_rd(rat_inst2_rd_in),
		.prf_inst2_rd(prf_inst2_rd),
		.inst1_rasup(rat_inst1_rasup),
		.inst2_rasup(rat_inst2_rasup),
		.inst1_rasdown(rat_inst1_rasdown),
		.inst2_rasdown(rat_inst2_rasdown),
		.inst1_ll(rat_inst1_memop == `MEMOP_LL),
		.inst2_ll(rat_inst2_memop == `MEMOP_LL),
		.inst1_place2(rat_inst1_place2),
		.inst2_place2(rat_inst2_place2),
		.inst1_tlb(rat_inst1_cp0op == `CP0OP_TLBP || rat_inst1_cp0op == `CP0OP_TLBR && rat_inst1_cp0op == `CP0OP_TLBWI || rat_inst1_cp0op == `CP0OP_TLBWR),
		.inst2_tlb(rat_inst2_cp0op == `CP0OP_TLBP || rat_inst2_cp0op == `CP0OP_TLBR && rat_inst2_cp0op == `CP0OP_TLBWI || rat_inst2_cp0op == `CP0OP_TLBWR),
		.inst1_entryhi(rat_inst1_exccode == `EXC_ITLBL || rat_inst1_exccode == `EXC_RTLBL),
		.inst2_entryhi(rat_inst2_exccode == `EXC_ITLBL || rat_inst2_exccode == `EXC_RTLBL),
		.inst1_fetchexc(rat_inst1_exccode == `EXC_AdEL || rat_inst1_exccode == `EXC_ITLBL || rat_inst1_exccode == `EXC_RTLBL),
		.inst2_fetchexc(rat_inst2_exccode == `EXC_AdEL || rat_inst2_exccode == `EXC_ITLBL || rat_inst2_exccode == `EXC_RTLBL),
		.wb_en1(cdb_controller[0].en),
		.wb_en2(cdb_controller[1].en),
		.wb_en3(cdb_controller[2].en),
		.wb_exccode1(cdb_controller[0].exccode),
		.wb_exccode2(cdb_controller[1].exccode),
		.wb_exccode3(cdb_controller[2].exccode),
		.inst1_branch_fail(predict_conflict1),
		.inst2_branch_fail(predict_conflict2),
		.wb_rob_index1(cdb_controller[0].rob_index),
		.wb_rob_index2(cdb_controller[1].rob_index),
		.wb_rob_index3(cdb_controller[2].rob_index),
		.wb_origin_rd1(wb_origin_rd1),
		.wb_origin_rd2(wb_origin_rd2),
		.rob_index1(rat_rob_index1),
		.rob_index2(rat_rob_index2),
		.out_rob_en1(rob_en1),
		.out_rob_en2(rob_en2),
		.out_rob_cp0_en1(rob_cp0_en1),
		.out_rob_cp0_en2(rob_cp0_en2),
		.out_inst1_type(rob_inst1_type),
		.out_inst2_type(rob_inst2_type),
		.out_branch_fail1(retire_branch_fail1),
		.out_branch_fail2(retire_branch_fail2),
		.out_isds1(rob_isds1),
		.out_isds2(rob_isds2),
		.out_branchds1(rob_branchds1),
		.out_branchds2(rob_branchds2),
		.out_rasup1(ras_up1),
		.out_rasup2(ras_up2),
		.out_rasdown1(ras_down1),
		.out_rasdown2(ras_down2),
		.out_ll1(rob_ll1),
		.out_ll2(rob_ll2),
		.out_entryhi1(rob_entryhi1),
		.out_entryhi2(rob_entryhi2),
		.out_fetchexc1(rob_fetchexc1),
		.out_fetchexc2(rob_fetchexc2),
		.out_exccode1(rob_exccode1),
		.out_exccode2(rob_exccode2),
		.out_pc1(rob_pc1),
		.out_pc2(rob_pc2),

		`ifdef ROB_DEBUG
			.debug_rob_inst1_in(debug_idrat_inst1_out),
			.debug_rob_iaddr1_in(debug_idrat_addr1_out),
			.debug_rob_inst2_in(debug_idrat_inst2_out),
			.debug_rob_iaddr2_in(debug_idrat_addr2_out),
			.debug_rob_wdata1_in(cdb_controller[0].data),
			.debug_rob_wdata2_in(cdb_controller[1].data),	
			.debug_rob_wdata3_in(cdb_controller[2].data),

	  		.debug_retire1_pc(debug_retire1_pc),
	    	.debug_retire1_rf_wen(debug_retire1_rf_wen),
	 		.debug_retire1_rf_wnum(debug_retire1_rf_wnum),
	    	.debug_retire1_rf_wdata(debug_retire1_rf_wdata),
	 		.debug_retire2_pc(debug_retire2_pc),
	 		.debug_retire2_rf_wen(debug_retire2_rf_wen),
	 		.debug_retire2_rf_wnum(debug_retire2_rf_wnum),
	 		.debug_retire2_rf_wdata(debug_retire2_rf_wdata),
			.debug_commit1(debug_commit1),
			.debug_commit2(debug_commit2),
			.debug_int(int_interrupt),
		`endif	
		.stop_retire(stop_retire),
		.out_rob_index1(rt_rob_index1),
		.out_rob_index2(rt_rob_index2),
		.rob_origin_rd1(rob_origin_rd1),
		.rob_origin_rd2(rob_origin_rd2),
		.rob_rd1(rob_rd1),
		.rob_rd2(rob_rd2),
		.flush_request(rob_flush),
		.direction1(rob_direction1),
		.direction2(rob_direction2),
		.out_rob_en1_pre(out_rob_en1_pre),
		.out_rob_en2_pre(out_rob_en2_pre),
		.out_cp0_en1_pre(out_rob_cp0_en1_pre),
		.out_cp0_en2_pre(out_rob_cp0_en2_pre)
	);
	assign rat_stall = rob_flush | prf_flush_request;

// DIS
	logic alu_inst1_rs_ready, alu_inst2_rs_ready, alu_inst1_rt_ready, alu_inst2_rt_ready;
	logic dis_alu_rs_ready1, dis_alu_rs_ready2, dis_alu_rt_ready1, dis_alu_rt_ready2;
	always_ff @(posedge clk)begin
		if(~dis_stall_req)begin
			prf_inst1_rs_ready <= prf_inst1_rs == 0 || prf_inst1_rs == next_wb_rd1 || prf_inst1_rs == next_wb_rd2 || prf_inst1_rs == next_wb_rd3;
			prf_inst1_rt_ready <= prf_inst1_rt == 0 || prf_inst1_rt == next_wb_rd1 || prf_inst1_rt == next_wb_rd2 || prf_inst1_rt == next_wb_rd3;
			prf_inst2_rs_ready <= prf_inst2_rs == 0 || prf_inst2_rs == next_wb_rd1 || prf_inst2_rs == next_wb_rd2 || prf_inst2_rs == next_wb_rd3;
			prf_inst2_rt_ready <= prf_inst2_rt == 0 || prf_inst2_rt == next_wb_rd1 || prf_inst2_rt == next_wb_rd2 || prf_inst2_rt == next_wb_rd3;
			alu_inst1_rs_ready <= prf_inst1_rs == 0 || prf_inst1_rs == next_wb_rd1 || prf_inst1_rs == next_wb_rd2 || prf_inst1_rs == next_wb_rd3 || (alu_prf_en1 && prf_inst1_rs == alu_prf_rd1) || (alu_prf_en2 && prf_inst1_rs == alu_prf_rd2);
			alu_inst1_rt_ready <= prf_inst1_rt == 0 || prf_inst1_rt == next_wb_rd1 || prf_inst1_rt == next_wb_rd2 || prf_inst1_rt == next_wb_rd3 || (alu_prf_en1 && prf_inst1_rt == alu_prf_rd1) || (alu_prf_en2 && prf_inst1_rt == alu_prf_rd2);
			alu_inst2_rs_ready <= prf_inst2_rs == 0 || prf_inst2_rs == next_wb_rd1 || prf_inst2_rs == next_wb_rd2 || prf_inst2_rs == next_wb_rd3 || (alu_prf_en1 && prf_inst2_rs == alu_prf_rd1) || (alu_prf_en2 && prf_inst2_rs == alu_prf_rd2);
			alu_inst2_rt_ready <= prf_inst2_rt == 0 || prf_inst2_rt == next_wb_rd1 || prf_inst2_rt == next_wb_rd2 || prf_inst2_rt == next_wb_rd3 || (alu_prf_en1 && prf_inst2_rt == alu_prf_rd1) || (alu_prf_en2 && prf_inst2_rt == alu_prf_rd2);
			dis_analyze_addr <= rat_analyze_addr;
			dis_inst1_branch <= rat_inst1_branch;
			dis_inst2_branch <= rat_inst2_branch;
		end
		else begin
			prf_inst1_rs_ready <= dis_inst1_rs_ready || dis_inst1_rs == next_wb_rd1 || dis_inst1_rs == next_wb_rd2 || dis_inst1_rs == next_wb_rd3;
			prf_inst1_rt_ready <= dis_inst1_rt_ready || dis_inst1_rt == next_wb_rd1 || dis_inst1_rt == next_wb_rd2 || dis_inst1_rt == next_wb_rd3;
			prf_inst2_rs_ready <= dis_inst2_rs_ready || dis_inst2_rs == next_wb_rd1 || dis_inst2_rs == next_wb_rd2 || dis_inst2_rs == next_wb_rd3;
			prf_inst2_rt_ready <= dis_inst2_rt_ready || dis_inst2_rt == next_wb_rd1 || dis_inst2_rt == next_wb_rd2 || dis_inst2_rt == next_wb_rd3;
			alu_inst1_rs_ready <= dis_alu_rs_ready1 || prf_inst1_rs == next_wb_rd1 || prf_inst1_rs == next_wb_rd2 || prf_inst1_rs == next_wb_rd3 || (alu_prf_en1 && prf_inst1_rs == alu_prf_rd1) || (alu_prf_en2 && prf_inst1_rs == alu_prf_rd2);
			alu_inst1_rt_ready <= dis_alu_rt_ready1 || prf_inst1_rt == next_wb_rd1 || prf_inst1_rt == next_wb_rd2 || prf_inst1_rt == next_wb_rd3 || (alu_prf_en1 && prf_inst1_rt == alu_prf_rd1) || (alu_prf_en2 && prf_inst1_rt == alu_prf_rd2);
			alu_inst2_rs_ready <= dis_alu_rs_ready2 || prf_inst2_rs == next_wb_rd1 || prf_inst2_rs == next_wb_rd2 || prf_inst2_rs == next_wb_rd3 || (alu_prf_en1 && prf_inst2_rs == alu_prf_rd1) || (alu_prf_en2 && prf_inst2_rs == alu_prf_rd2);
			alu_inst2_rt_ready <= dis_alu_rt_ready2 || prf_inst2_rt == next_wb_rd1 || prf_inst2_rt == next_wb_rd2 || prf_inst2_rt == next_wb_rd3 || (alu_prf_en1 && prf_inst2_rt == alu_prf_rd1) || (alu_prf_en2 && prf_inst2_rt == alu_prf_rd2);
		end
	end

	RATDIS_reg rat_dis_reg(
		.cpu_clk(clk),
		.clear(resetn == 1'b0 || clear_bus_prf || (rat_stall & ~dis_stall_req)),
		.stall(dis_stall_req),
		.rat_inst1_en(rat_inst1_en),
		.rat_inst2_en(rat_inst2_en_in),
		.rat_inst1_origin_rs(rat_inst1_rs),
		.rat_inst2_origin_rs(rat_inst2_rs),
		.rat_inst1_rs(prf_inst1_rs),
		.rat_inst1_rt(prf_inst1_rt),
		.rat_inst1_rd(prf_inst1_rd),
		.rat_inst2_rs(prf_inst2_rs),
		.rat_inst2_rt(prf_inst2_rt),
		.rat_inst2_rd(prf_inst2_rd),
		.rat_rob_index1(rat_rob_index1),
		.rat_rob_index2(rat_rob_index2),
		.rat_rob_direction1(rob_direction1),
		.rat_rob_direction2(rob_direction2),
		.rat_inst1_src1(rat_inst1_src1),
		.rat_inst1_src2(rat_inst1_src2),
		.rat_inst2_src1(rat_inst2_src1),
		.rat_inst2_src2(rat_inst2_src2),
		.rat_inst1_type(rat_inst1_type),
		.rat_inst1_aluop(rat_inst1_aluop),
		.rat_inst2_type(rat_inst2_type_in),
		.rat_inst2_aluop(rat_inst2_aluop),
		.rat_inst1_memop(rat_inst1_memop),
		.rat_inst2_memop(rat_inst2_memop),
		.rat_inst1_exccode(rat_inst1_exccode),
		.rat_inst2_exccode(rat_inst2_exccode),
		.rat_inst1_cp0op(rat_inst1_cp0op),
		.rat_inst2_cp0op(rat_inst2_cp0op),
		.rat_inst1_multop(rat_inst1_multop),
		.rat_inst2_multop(rat_inst2_multop),

		`ifdef CPU_DEBUG
			.debug_ratdis_inst1_in(debug_idrat_inst1_out),
			.debug_ratdis_inst2_in(debug_idrat_inst2_out),
			.debug_ratdis_inst1_out(debug_ratdis_inst1_out),
			.debug_ratdis_inst2_out(debug_ratdis_inst2_out),
		`endif

		.dis_inst1_en(dis_inst1_en),
		.dis_inst2_en(dis_inst2_en),
		.dis_inst1_origin_rs(dis_inst1_origin_rs),
		.dis_inst2_origin_rs(dis_inst2_origin_rs),
		.dis_inst1_rs(dis_inst1_rs_in),
		.dis_inst1_rt(dis_inst1_rt_in),
		.dis_inst1_rd(dis_inst1_rd),
		.dis_inst2_rs(dis_inst2_rs_in),
		.dis_inst2_rt(dis_inst2_rt_in),
		.dis_inst2_rd(dis_inst2_rd),
		.dis_rob_index1(dis_rob_index1),
		.dis_rob_index2(dis_rob_index2),
		.dis_rob_direction1(dis_rob_direction1),
		.dis_rob_direction2(dis_rob_direction2),
		.dis_inst1_src1(dis_inst1_src1_in),
		.dis_inst1_src2(dis_inst1_src2_in),
		.dis_inst2_src1(dis_inst2_src1_in),
		.dis_inst2_src2(dis_inst2_src2_in),
		.dis_inst1_type(dis_inst1_type),
		.dis_inst1_aluop(dis_inst1_aluop),
		.dis_inst2_type(dis_inst2_type),
		.dis_inst2_aluop(dis_inst2_aluop),
		.dis_inst1_memop(dis_inst1_memop),
		.dis_inst2_memop(dis_inst2_memop),
		.dis_inst1_exccode(dis_inst1_exccode),
		.dis_inst2_exccode(dis_inst2_exccode),
		.dis_inst1_cp0op(dis_inst1_cp0op),
		.dis_inst2_cp0op(dis_inst2_cp0op),
		.dis_inst1_multop(dis_inst1_multop),
		.dis_inst2_multop(dis_inst2_multop)
	);

	assign dis_inst1_rs_ready = prf_inst1_src1_en | prf_inst1_rs_ready;
	assign dis_inst1_rt_ready = prf_inst1_src2_en | prf_inst1_rt_ready;
	assign dis_inst2_rs_ready = prf_inst2_src1_en | prf_inst2_rs_ready;
	assign dis_inst2_rt_ready = prf_inst2_src2_en | prf_inst2_rt_ready;
	assign dis_alu_rs_ready1 = prf_inst1_src1_en | alu_inst1_rs_ready;
	assign dis_alu_rt_ready1 = prf_inst1_src2_en | alu_inst1_rt_ready;
	assign dis_alu_rs_ready2 = prf_inst2_src1_en | alu_inst2_rs_ready;
	assign dis_alu_rt_ready2 = prf_inst2_src2_en | alu_inst2_rt_ready;
	assign dis_inst1_rs = dis_inst1_rs_in;
	assign dis_inst1_rt = dis_inst1_rt_in;
	assign dis_inst2_rs = dis_inst2_rs_in;
	assign dis_inst2_rt = dis_inst2_rt_in;

	assign dis_inst1_src1 = dis_inst1_src1_in;
	assign dis_inst1_src2 = dis_inst1_src2_in;
	assign dis_inst2_src1 = dis_inst2_src1_in;
	assign dis_inst2_src2 = dis_inst2_src2_in;

	assign dis_alu_en1 = dis_inst1_en && (dis_inst1_type == `INST_TYPE_ALU || dis_inst1_type == `INST_TYPE_BRANCH || dis_inst1_exccode == `EXC_RI);
	assign dis_alu_en2 = dis_inst1_en && (dis_inst2_type == `INST_TYPE_ALU || dis_inst2_type == `INST_TYPE_BRANCH || dis_inst2_exccode == `EXC_RI);
	AluIssueQueue alu_issue_queue(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.clear(clear_bus_issue),
		.stall(dis_stall_req),
		.en1(dis_alu_en1),
		.en2(dis_alu_en2),
		.inst1_branch(dis_inst1_type == `INST_TYPE_BRANCH),
		.inst2_branch(dis_inst2_type == `INST_TYPE_BRANCH),
		.inst1_rs(dis_inst1_rs),
		.inst1_rt(dis_inst1_rt),
		.inst1_rd(dis_inst1_rd),
		.inst2_rs(dis_inst2_rs),
		.inst2_rt(dis_inst2_rt),
		.inst2_rd(dis_inst2_rd),
		.inst1_exccode(dis_inst1_exccode),
		.inst2_exccode(dis_inst2_exccode),
		.inst1_rs_ready(dis_inst1_rs_ready),
		.inst1_rt_ready(dis_inst1_rt_ready),
		.inst2_rs_ready(dis_inst2_rs_ready),
		.inst2_rt_ready(dis_inst2_rt_ready),
		.inst1_src1(dis_inst1_src1),
		.inst1_src2(dis_inst1_src2),
		.inst2_src1(dis_inst2_src1),
		.inst2_src2(dis_inst2_src2),
		.inst1_aluop(dis_inst1_aluop),
		.inst2_aluop(dis_inst2_aluop),
		.rob_index1(dis_rob_index1),
		.rob_index2(dis_rob_index2),
		.rob_direction1(dis_rob_direction1),
		.rob_direction2(dis_rob_direction2),
		.branch_index(branch_index),
		.wb_en1(cdb_controller[0].en),
		.wb_en2(cdb_controller[1].en),
		.wb_en3(cdb_controller[2].en),
		.wb_rd1(cdb_controller[0].rd),
		.wb_rd2(cdb_controller[1].rd),
		.wb_rd3(cdb_controller[2].rd),
		.wb_src1(cdb_controller[0].data),
		.wb_src2(cdb_controller[1].data),
		.wb_src3(cdb_controller[2].data),
		.inst1_acceptable(alu_inst1_acceptable),
		.inst2_acceptable(alu_inst2_acceptable),
		.prf_src1(alu_prf_src1),
		.prf_src2(alu_prf_src2),
		.prf_src3(alu_prf_src3),
		.prf_src4(alu_prf_src4),

		`ifdef CPU_DEBUG
			.debug_inst1_in(debug_ratdis_inst1_out),
			.debug_inst2_in(debug_ratdis_inst2_out),
		`endif

		.prf_rs1(alu_prf_rs1),
		.prf_rs2(alu_prf_rs2),
		.prf_rt1(alu_prf_rt1),
		.prf_rt2(alu_prf_rt2),
		.prf_en1(alu_prf_en1),
		.prf_en2(alu_prf_en2),
		.prf_rd1(alu_prf_rd1),
		.prf_rd2(alu_prf_rd2),
		.out_inst1_valid(alu_inst1_valid),
		.out_inst2_valid(alu_inst2_valid),
		.out_alu1_valid(out_alu1_valid),
		.out_alu2_valid(out_alu2_valid),
		.out_inst1_rd(alu_inst1_rd),
		.out_inst2_rd(alu_inst2_rd),
		.out_inst1_src1(alu_inst1_src1),
		.out_inst1_src2(alu_inst1_src2),
		.out_inst2_src1(alu_inst2_src1),
		.out_inst2_src2(alu_inst2_src2),
		.out_inst1_rob_index(alu_inst1_rob_index),
		.out_inst2_rob_index(alu_inst2_rob_index),
		.out_inst1_branch_index(alu_branch_index1),
		.out_inst2_branch_index(alu_branch_index2),
		.out_inst1_branch(alu_inst1_branch),
		.out_inst2_branch(alu_inst2_branch),
		.out_inst1_aluop(alu_inst1_aluop),
		.out_inst2_aluop(alu_inst2_aluop),
		.out_inst1_exccode(alu_inst1_exccode),
		.out_inst2_exccode(alu_inst2_exccode),
		.dis_alu_stall_request(dis_alu_stall_request)
	);

	assign dis_mult_en = dis_inst1_en && dis_inst1_type == `INST_TYPE_MULT;
	MultIssueQueue mutl_issue_queue(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.clear(clear_bus_issue),
		.stall(dis_stall_req),
		.en(dis_mult_en),
		.inst_rs(dis_inst1_rs),
		.inst_rt(dis_inst1_rt),
		.inst_rs2(dis_inst2_rs),
		.inst_rt2(dis_inst2_rt),
		.inst_exccode(dis_inst1_exccode),
		.inst_rs_ready(dis_inst1_rs_ready),
		.inst_rt_ready(dis_inst1_rt_ready),
		.inst_rs2_ready(dis_inst2_rs_ready),
		.inst_rt2_ready(dis_inst2_rt_ready),
		.inst_rob_direction(dis_rob_direction1),
		.inst_rd1(dis_inst1_rd),
		.inst_rd2(dis_inst2_rd),
		.prf_src1(mult_prf_src1),
		.prf_src2(mult_prf_src2),
		.inst_multop(dis_inst1_multop),
		.rob_index1(dis_rob_index1),
		.rob_index2(dis_rob_index2),
		.wb_en1(cdb_controller[0].en),
		.wb_en2(cdb_controller[1].en),
		.wb_en3(cdb_controller[2].en),
		.wb_rd1(cdb_controller[0].rd),
		.wb_rd2(cdb_controller[1].rd),
		.wb_rd3(cdb_controller[2].rd),
		.inst_acceptable(mult_inst_acceptable),
		
		.search_rs(mult_prf_rs),
		.search_rt(mult_prf_rt),
		.out_inst_valid(mult_inst_valid),
		.out_inst_rd1(mult_inst_rd1),
		.out_inst_rd2(mult_inst_rd2),
		.out_inst_src1(mult_inst_src1),
		.out_inst_src2(mult_inst_src2),
		.out_inst_src3(mult_inst_src3),
		.out_inst_src4(mult_inst_src4),
		.out_inst_src1_unsign(mult_inst_src1_unsign),
		.out_inst_src2_unsign(mult_inst_src2_unsign),
		.out_inst_src1_issign(mult_inst_src1_issign),
		.out_inst_src2_issign(mult_inst_src2_issign),
		.out_inst_exccode(mult_inst_exccode),
		.out_inst_rob_index1(mult_inst_rob_index1),
		.out_inst_rob_index2(mult_inst_rob_index2),
		.out_inst_type(mult_inst_type),
		.dis_mult_stall_request(dis_mult_stall_request)
	);
	
	assign dis_mem_en1 = dis_inst1_en && dis_inst1_type == `INST_TYPE_MEM;
	assign dis_mem_en2 = dis_inst2_en && dis_inst2_type == `INST_TYPE_MEM;
	assign mem_inst_wb_receive = mem_end;

	MemIssueQueue1 mem_issue_queue(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.clear(clear_bus_issue),
		.branch_fail_clear(predict_clear_next),
		.stall(dis_stall_req),
		.en1(dis_mem_en1),
		.en2(dis_mem_en2),
		.inst1_rs(dis_inst1_rs),
		.inst1_rt(dis_inst1_rt),
		.inst1_rd(dis_inst1_rd),
		.inst2_rs(dis_inst2_rs),
		.inst2_rt(dis_inst2_rt),
		.inst2_rd(dis_inst2_rd),
		.inst1_rs_ready(dis_inst1_rs_ready),
		.inst1_rt_ready(dis_inst1_rt_ready),
		.inst2_rs_ready(dis_inst2_rs_ready),
		.inst2_rt_ready(dis_inst2_rt_ready),
		.inst1_exccode(dis_inst1_exccode),
		.inst2_exccode(dis_inst2_exccode),
		.inst1_memop(dis_inst1_memop),
		.inst2_memop(dis_inst2_memop),
		.search1(mem_write_rs),
		.search2(mem_write_rt),
		.search3(mem_read_rs),
		.search4_en(search4_en),
		.search4(mem_read_rt),
		.data1(mem_write_src1),
		.data2(mem_write_src2),
		.data3(mem_read_src1),
		.data4(prf_cp0_data),
		.inst1_src2(dis_inst1_src2_in),
		.inst2_src2(dis_inst2_src2_in),
		.rob_index1(dis_rob_index1),
		.rob_index2(dis_rob_index2),

		.retire_en1(rob_en1),
		.retire_en2(rob_en2),
		.retire_ll1(rob_ll1),
		.retire_ll2(rob_ll2),
		.retire_rob_index1(rt_rob_index1),
		.retire_rob_index2(rt_rob_index2),

		.wb_en1(cdb_controller[0].en),
		.wb_en2(cdb_controller[1].en),
		.wb_en3(cdb_controller[2].en),
		.wb_rd1(cdb_controller[0].rd),
		.wb_rd2(cdb_controller[1].rd),
		.wb_rd3(cdb_controller[2].rd),
		.inst_wb_receive(mem_inst_wb_receive),

		.mem_end(mem_end),
		.mem_rd(mem_rd),
		.next_mem_rd(mem_next_rd),
		.mem_rob_index(mem_rob_index),
		.mem_data(mem_data),
		.mem_exccode(mem_exccode),
		.dis_mem_stall_req(dis_mem_stall_req),
		.mem_addr(mem_addr),
		.vaddr_we(vaddr_we),
		.vaddr_rob_index(vaddr_rob_index),
		.entryhi_we(mem_entryhi_we),

		.data_addr_ok(data_addr_ok),
		.data_data_ok(data_data_ok),
		.write_accept(data_write_accept),
		.data_clear(data_clear),
		.data_success(data_success),
		.data_waddr_ok(data_waddr_ok),
		.data_uncache_ok(data_uncache_ok),
		.data_rdata(data_rdata),
		.read_queue_index(read_queue_index),
		.enable_miss_back(data_enable_miss_back),
		.mshr_data_ok(mshr_data_ok),
		.mshr_queue_index(mshr_queue_index),
		.mshr_data(mshr_data),
		.rdata_tlb_invalid(rdata_tlb_invalid),
		.rdata_tlb_refill(rdata_tlb_refill),
		.wdata_tlb_invalid(wdata_tlb_invalid),
		.wdata_tlb_refill(wdata_tlb_refill),
		.data_tlb_modify(data_tlb_modify),
		
		.data_req(data_req),
		.data_write_req(data_write_req),
		.enable_miss(data_enable_miss),
		.out_queue_index(data_issue_queue_index),
		.data_wstrb(data_wstrb),
		.data_rwstrb(data_rwstrb),
		.data_addr(data_addr),
		.data_waddr(data_waddr),
		.data_wdata(data_wdata),
		.data_write_ptag(data_write_ptag),
		.vwtag(vwtag),
		.pwtag(pwtag),
		.prtag(prtag),
		.data_runcache(data_runcache),
		.data_wuncache(data_wuncache),
		.data_abandon_lookup(data_abandon_lookup),
		.uncache_req(uncache_req),
		.uncache_wr(uncache_wr),
		.uncache_wstrb(uncache_wstrb),
		.uncache_addr(uncache_addr),
		.uncache_queue_index(uncache_queue_index),
		.uncache_data(uncache_data),
		.uncache_data_ok(uncache_data_ok)
	);

	assign dis_cp0_en1 = dis_inst1_en && dis_inst1_type == `INST_TYPE_CP0;
	assign dis_cp0_en2 = dis_inst2_en && dis_inst2_type == `INST_TYPE_CP0;
	assign cp0_wb_receive = !search4_en && (cdb1_use && cdb_controller[0].next_select == `UNIT_CP0 || cdb2_use && cdb_controller[1].next_select == `UNIT_CP0 || cdb3_use && cdb_controller[2].next_select == `UNIT_CP0);
	// mfc0 and mtc0
	CP0IssueQueue cp0_issue_queue(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.clear(clear_bus_issue),
		.stall(dis_stall_req),
		.inst1_en(dis_cp0_en1),
		.inst2_en(dis_cp0_en2),
		.inst1_op(dis_inst1_cp0op),
		.inst2_op(dis_inst2_cp0op),
		.inst1_exccode(dis_inst1_exccode),
		.inst2_exccode(dis_inst2_exccode),
		.inst1_rs_ready(dis_inst1_rs_ready),
		.inst2_rs_ready(dis_inst2_rs_ready),
		.inst1_rt_ready(dis_inst1_rt_ready),
		.inst2_rt_ready(dis_inst2_rt_ready),
		.inst1_rs((dis_inst1_cp0op == `CP0OP_MTC0) ? dis_inst1_rt : dis_inst1_cp0op == `CP0OP_CACHE ? dis_inst1_rs : dis_inst1_origin_rs),
		.inst2_rs((dis_inst2_cp0op == `CP0OP_MTC0) ? dis_inst2_rt : dis_inst2_cp0op == `CP0OP_CACHE ? dis_inst2_rs : dis_inst2_origin_rs),
		.inst1_rd((dis_inst1_cp0op == `CP0OP_MTC0) ? dis_inst1_origin_rs : dis_inst1_rd),
		.inst2_rd((dis_inst2_cp0op == `CP0OP_MTC0) ? dis_inst2_origin_rs : dis_inst2_rd),
		.inst1_rob_index(dis_rob_index1),
		.inst2_rob_index(dis_rob_index2),
		.inst1_cacheop(dis_inst1_src1_in[4: 0]),
		.inst2_cacheop(dis_inst2_src1_in[4: 0]),
		.inst1_src2(dis_inst1_src2_in),
		.inst2_src2(dis_inst2_src2_in),
		.cp0_receive(cp0_wb_receive),
		.wb_en1(cdb_controller[0].en),
		.wb_en2(cdb_controller[1].en),
		.wb_en3(cdb_controller[2].en),
		.wb_rd1(cdb_controller[0].rd),
		.wb_rd2(cdb_controller[1].rd),
		.wb_rd3(cdb_controller[2].rd),
		.retire_en1(rob_en1),
		.retire_en2(rob_en2),
		.retire_cp0_en1(rob_cp0_en1),
		.retire_cp0_en2(rob_cp0_en2),
		.retire_rob_index1(rt_rob_index1),
		.retire_rob_index2(rt_rob_index2),
		.prf_data(prf_cp0_data),
		.cp0_data(cp0_rdata),
		.prf_rt(prf_cp0_rt),
		.cp0_end(cp0_end),
		.cp0_we(cp0_we),
		.cp0_rd(cp0_rd),
		.cp0_wdata(cp0_wdata),
		.cp0_op(cp0_op),
		.tlb_inst_en(cp0_tlb_inst_en),
		.tlb_type(cp0_tlb_type),
		.next_rd(cp0_next_rd),
		.out_rd(cp0_wb_rd),
		.out_rob_index(cp0_wb_rob_index),
		.out_data(cp0_wb_data),
		.out_exccode(cp0_wb_exccode),
		.dis_cp0_stall_req(dis_cp0_stall_req),
		.cp0_rt(cp0_rt),
		.rob_pc(rob_pc1),
		.rob_pc4(rob_pc2),
		.icache_ready(icache_ready),
		.dcache_ready(dcache_ready),
		.cache_valid(cache_valid),
		.cacheop(cacheop),
		.cache_addr(cache_addr),
		.waiting(waiting)
	);

	assign dis_stall_req = dis_alu_stall_request || dis_mult_stall_request || dis_mem_stall_req || dis_cp0_stall_req;

// EXE
	assign alu_inst1_wb_receive = exe_alu_inst1_end;
	assign alu_inst2_wb_receive = exe_alu_inst2_end;
	AluFunctionUnit alu_function_unit(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.flush(clear_bus_wb),
		.inst1_valid(alu_inst1_valid),
		.inst2_valid(alu_inst2_valid),
		.inst1_branch(alu_inst1_branch),
		.inst2_branch(alu_inst2_branch),
		.inst1_rd(alu_inst1_rd),
		.inst2_rd(alu_inst2_rd),
		.inst1_src1(alu_inst1_src1),
		.inst1_src2(alu_inst1_src2),
		.inst2_src1(alu_inst2_src1),
		.inst2_src2(alu_inst2_src2),
		.inst1_rob_index(alu_inst1_rob_index),
		.inst2_rob_index(alu_inst2_rob_index),
		.inst1_branch_index(alu_branch_index1),
		.inst2_branch_index(alu_branch_index2),
		.inst1_aluop(alu_inst1_aluop),
		.inst2_aluop(alu_inst2_aluop),
		.inst1_wb_receive(alu_inst1_wb_receive),
		.inst2_wb_receive(alu_inst2_wb_receive),
		.before_alu1_valid(out_alu1_valid),
		.before_alu2_valid(out_alu2_valid),
		// .conflict1(out_alu1_conflict),
		// .conflict2(out_alu2_conflict),
		.inst1_exccode(alu_inst1_exccode),
		.inst2_exccode(alu_inst2_exccode),
		.inst1_end(exe_alu_inst1_end),
		.inst2_end(exe_alu_inst2_end),
		.out_inst1_rd(exe_alu_inst1_rd),
		.out_inst2_rd(exe_alu_inst2_rd),
		.out_inst1_rob_index(exe_alu_inst1_rob_index),
		.out_inst2_rob_index(exe_alu_inst2_rob_index),
		.out_inst1_ans(exe_alu_inst1_ans),
		.out_inst2_ans(exe_alu_inst2_ans),
		.inst1_acceptable(alu_inst1_acceptable),
		.inst2_acceptable(alu_inst2_acceptable),
		.inst1_next_rd(alu_next_rd1),
		.inst2_next_rd(alu_next_rd2),
		.branch_ans1(alu_branch_ans1),
		.branch_ans2(alu_branch_ans2),
		.out_inst1_branch(wb_alu_branch1),
		.out_inst2_branch(wb_alu_branch2),
		.out_branch_index1(exe_alu_branch_index1),
		.out_branch_index2(exe_alu_branch_index2),
		.out_exccode1(exe_alu_inst1_exccode),
		.out_exccode2(exe_alu_inst2_exccode)
	);
	
	assign mult_inst_wb_receive = cdb1_use && cdb_controller[0].next_select == `UNIT_MULT || 
	cdb2_use && cdb_controller[1].next_select == `UNIT_MULT || cdb3_use && cdb_controller[2].next_select == `UNIT_MULT;
	multDivFunctionUnit muldiv_function_unit(
		.clk(clk),
		.resetn(resetn),
		.flush(clear_bus_wb),
		.inst_valid(mult_inst_valid),
		.inst_src1(mult_inst_src1),
		.inst_src2(mult_inst_src2),
		.inst_src3(mult_inst_src3),
		.inst_src4(mult_inst_src4),
		.inst_src1_unsign(mult_inst_src1_unsign),
		.inst_src2_unsign(mult_inst_src2_unsign),
		.inst_src1_issign(mult_inst_src1_issign),
		.inst_src2_issign(mult_inst_src2_issign),
		.inst_exccode(mult_inst_exccode),
		.inst_rd1(mult_inst_rd1),
		.inst_rd2(mult_inst_rd2),
		.inst_rob_index1(mult_inst_rob_index1),
		.inst_rob_index2(mult_inst_rob_index2),
		.inst_type(mult_inst_type),
		.inst_wb_receive(mult_inst_wb_receive),

		.next_rd(mult_next_rd),
		.out_src(mult_src),
		.out_rd(mult_rd),
		.out_rob_index(mult_rob_index),
		.out_inst_exccode(mult_fu_exccode),
		.inst_end(mult_inst_end),
		.inst_acceptable(mult_inst_acceptable)
	);

	// 用于中断的pc，目的是获得当前退休指令的后一条指令地址
	// 如果当前rob中可以获得下一条指令地址，则使用rob中的地址
	// 如果出现branch_fail获cp0_fail，则使用跳转地址


	assign rob_pc4 = rob_pc1 + 4;
	assign rob_pc8 = rob_pc1 + 8;
	assign rob_exccode = rob_cp0_en1 ? rob_exccode1 : rob_exccode2;
	assign cp0_rob_index = rob_cp0_en1 ? rt_rob_index1 : rt_rob_index2;
	assign cp0_pc = rob_cp0_en1 ? rob_pc1 : rob_pc2;
	assign cp0_retire_en = rob_cp0_en1 | rob_cp0_en2;
	assign hard_int_addr = out_rob_en1_pre | out_rob_cp0_en1_pre ? rob_pc1 : rob_pc2;
	assign hard_int_ds = out_rob_en1_pre | out_rob_cp0_en1_pre ? rob_isds1 : rob_isds2;
	assign stop_retire = int_interrupt;
	always_ff @(posedge clk)begin
		debug_int <= int_interrupt;
	end
	CP0 cp0(
		.cpu_clk(clk),
		.cpu_rst_n(resetn),
		.clear(clear_bus_wb),
		.retire_en(cp0_retire_en),
		.normal_retire_en((out_rob_en1_pre | out_rob_cp0_en1_pre | out_rob_cp0_en2_pre | waiting)), // 第二条指令可能是空指令或者乘除法，如果直接中断会导致这条指令被重复执行
		.retire_exccode(rob_exccode),
		.wdata1(cp0_wdata),
		.waddr1(cp0_rd),
		.rdata1(cp0_rdata),
		.raddr1(cp0_rt),
		.we1(cp0_we),
		.cp0_op(cp0_op),
		.delay(rob_cp0_en1 ? rob_isds1 : rob_isds2),
		.pc(cp0_pc),
		.hard_int_pc(hard_int_addr),
		.hard_int_ds(hard_int_ds),
		.int_i(ext_int),
		// .debug_int(debug_int),
		.tlb_we(cp0_tlb_inst_en),
		.tlb_type(cp0_tlb_type),
		// .weak_vaddr_we(if_exccode),
		// .weak_vaddr(cp0_weak_addr),
		.vaddr_we(!clear_bus_wb && (rob_cp0_en1 && rob_fetchexc1 || rob_cp0_en2 && rob_fetchexc2 || vaddr_we && (vaddr_rob_index == cp0_rob_index))),
		.entryhi_we(!clear_bus_wb && (rob_cp0_en1 && rob_entryhi1 || rob_cp0_en2 && rob_entryhi2 || cp0_retire_en && mem_entryhi_we && (vaddr_rob_index == cp0_rob_index))),
		.vaddr(rob_cp0_en1 && rob_fetchexc1 || rob_cp0_en2 && rob_fetchexc2 ? cp0_pc : mem_addr),
		// .soft_en(cp0_soft_en),
		.exception_flush(cp0_clear),
		.excaddr(cp0_addr),
		.Caseint(int_interrupt),
		.user_mode(user_mode),
`ifdef CPU_DEBUG
		.debug_cp0_cause(debug_cp0_cause),
		.debug_cp0_random(debug_cp0_random),
		.debug_cp0_count(debug_cp0_count),
		.cp0_issue_queue_end(cp0_end && cp0_wb_receive),
`endif
		.entry_lo0_in	(tlb_entry_lo0_in	),
		.entry_lo1_in	(tlb_entry_lo1_in	),
		.page_mask_in	(tlb_page_mask_in	),	
		.entry_hi_in	(tlb_entry_hi_in	),
		.index_in		(tlb_index_in		),
		.entry_hi_out	(cp0_entry_hi_out	), 
		.taglo_out 		(cp0_taglo_out		),
		.page_mask_out	(cp0_page_mask_out	),
		.entry_lo0_out	(cp0_entry_lo0_out	),
		.entry_lo1_out	(cp0_entry_lo1_out	),
		.index_out		(cp0_index_out		),
		.random_out		(cp0_random_out		),
		.kseg0_uncache	(kseg0_uncache)
	);

// WB

	assign end_num = exe_alu_inst1_end + exe_alu_inst2_end + mem_end + mult_inst_end + cp0_end;
	always_comb begin
		// alu have the highest privilege
		cdb1_use = exe_alu_inst1_end | mult_inst_end | cp0_end;
		cdb2_use = exe_alu_inst1_end & (mult_inst_end | cp0_end) | ~exe_alu_inst1_end & mult_inst_end & cp0_end | exe_alu_inst2_end;
		cdb3_use = end_num[2] | end_num[1] & end_num[0] | mem_end; // end_num >= 3
		cdb_controller[0].next_select = exe_alu_inst1_end ? `UNIT_ALU1 : 
									mult_inst_end ? `UNIT_MULT : 
									cp0_end ? `UNIT_CP0 : 0;
		cdb_controller[1].next_select = exe_alu_inst2_end ? `UNIT_ALU2 :
									mult_inst_end && cdb_controller[0].next_select != `UNIT_MULT ? `UNIT_MULT : cp0_end && cdb_controller[0].next_select != `UNIT_CP0 ? `UNIT_CP0 : 0;
		cdb_controller[2].next_select = mem_end ? `UNIT_MEM : 
										mult_inst_end && (cdb_controller[0].next_select != `UNIT_MULT && cdb_controller[1].next_select != `UNIT_MULT) ? `UNIT_MULT :
										cp0_end && (cdb_controller[0].next_select != `UNIT_CP0 && cdb_controller[1].next_select != `UNIT_CP0) ? `UNIT_CP0 : 0;
		next_wb_rd1 = exe_alu_inst1_end ? alu_next_rd1 :
					mult_inst_end ? mult_next_rd :
					cp0_end ? cp0_next_rd : 0;
		next_wb_rd2 = exe_alu_inst2_end ? alu_next_rd2 :
					mult_inst_end && cdb_controller[0].next_select != `UNIT_MULT ? mult_next_rd : 
					cp0_end && cdb_controller[0].next_select != `UNIT_CP0 ? cp0_next_rd : 0;
		next_wb_rd3 = mem_end ? mem_next_rd :
					mult_inst_end && (cdb_controller[0].next_select != `UNIT_MULT && cdb_controller[1].next_select != `UNIT_MULT) ? mult_next_rd :
					cp0_end && (cdb_controller[0].next_select != `UNIT_CP0 && cdb_controller[1].next_select != `UNIT_CP0) ? cp0_next_rd : 0;


		case(cdb_controller[0].select)
			`UNIT_ALU1:begin
				cdb_controller[0].rd = exe_alu_inst1_rd;
				cdb_controller[0].rob_index = exe_alu_inst1_rob_index;
				cdb_controller[0].data = exe_alu_inst1_ans;
				cdb_controller[0].exccode = exe_alu_inst1_exccode;
			end
			`UNIT_ALU2:begin
				cdb_controller[0].rd = exe_alu_inst2_rd;
				cdb_controller[0].rob_index = exe_alu_inst2_rob_index;
				cdb_controller[0].data = exe_alu_inst2_ans;
				cdb_controller[0].exccode = exe_alu_inst2_exccode;
			end
			`UNIT_MEM:begin
				cdb_controller[0].rd = mem_rd;
				cdb_controller[0].rob_index = mem_rob_index;
				cdb_controller[0].data = mem_data;
				cdb_controller[0].exccode = mem_exccode;
			end
			`UNIT_MULT: begin
				cdb_controller[0].rd = mult_rd;
				cdb_controller[0].rob_index = mult_rob_index;
				cdb_controller[0].data = mult_src;
				cdb_controller[0].exccode = mult_fu_exccode;
			end
			`UNIT_CP0: begin
				cdb_controller[0].rd = cp0_wb_rd;
				cdb_controller[0].rob_index = cp0_wb_rob_index;
				cdb_controller[0].data = cp0_wb_data;
				cdb_controller[0].exccode = cp0_wb_exccode;
			end
			default:begin
				cdb_controller[0].rd = 0;
				cdb_controller[0].rob_index = 0;
				cdb_controller[0].data = 0;
				cdb_controller[0].exccode = `EXC_NONE;
			end
		endcase
		case(cdb_controller[1].select)
			`UNIT_ALU1:begin
				cdb_controller[1].rd = exe_alu_inst1_rd;
				cdb_controller[1].rob_index = exe_alu_inst1_rob_index;
				cdb_controller[1].data = exe_alu_inst1_ans;
				cdb_controller[1].exccode = exe_alu_inst1_exccode;
			end
			`UNIT_ALU2:begin
				cdb_controller[1].rd = exe_alu_inst2_rd;
				cdb_controller[1].rob_index = exe_alu_inst2_rob_index;
				cdb_controller[1].data = exe_alu_inst2_ans;
				cdb_controller[1].exccode =exe_alu_inst2_exccode;
			end
			`UNIT_MEM:begin
				cdb_controller[1].rd = mem_rd;
				cdb_controller[1].rob_index = mem_rob_index;
				cdb_controller[1].data = mem_data;
				cdb_controller[1].exccode = mem_exccode;
			end
			`UNIT_MULT: begin
				cdb_controller[1].rd = mult_rd;
				cdb_controller[1].rob_index = mult_rob_index;
				cdb_controller[1].data = mult_src;
				cdb_controller[1].exccode = mult_fu_exccode;
			end
			`UNIT_CP0: begin
				cdb_controller[1].rd = cp0_wb_rd;
				cdb_controller[1].rob_index = cp0_wb_rob_index;
				cdb_controller[1].data = cp0_wb_data;
				cdb_controller[1].exccode = cp0_wb_exccode;
			end
			default:begin
				cdb_controller[1].rd = 0;
				cdb_controller[1].rob_index = 0;
				cdb_controller[1].data = 0;
				cdb_controller[1].exccode = `EXC_NONE;
			end
		endcase
		case(cdb_controller[2].select)
			`UNIT_ALU1:begin
				cdb_controller[2].rd = exe_alu_inst1_rd;
				cdb_controller[2].rob_index = exe_alu_inst1_rob_index;
				cdb_controller[2].data = exe_alu_inst1_ans;
				cdb_controller[2].exccode = exe_alu_inst1_exccode;
			end
			`UNIT_ALU2:begin
				cdb_controller[2].rd = exe_alu_inst2_rd;
				cdb_controller[2].rob_index = exe_alu_inst2_rob_index;
				cdb_controller[2].data = exe_alu_inst2_ans;
				cdb_controller[2].exccode =exe_alu_inst2_exccode;
			end
			`UNIT_MEM:begin
				cdb_controller[2].rd = mem_rd;
				cdb_controller[2].rob_index = mem_rob_index;
				cdb_controller[2].data = mem_data;
				cdb_controller[2].exccode = mem_exccode;
			end
			`UNIT_MULT: begin
				cdb_controller[2].rd = mult_rd;
				cdb_controller[2].rob_index = mult_rob_index;
				cdb_controller[2].data = mult_src;
				cdb_controller[2].exccode = mult_fu_exccode;
			end
			`UNIT_CP0: begin
				cdb_controller[2].rd = cp0_wb_rd;
				cdb_controller[2].rob_index = cp0_wb_rob_index;
				cdb_controller[2].data = cp0_wb_data;
				cdb_controller[2].exccode = cp0_wb_exccode;
			end
			default:begin
				cdb_controller[2].rd = 0;
				cdb_controller[2].rob_index = 0;
				cdb_controller[2].data = 0;
				cdb_controller[2].exccode = `EXC_NONE;
			end
		endcase
	end


	always_ff @(posedge clk)begin
		if(resetn == 1'b0 || clear_bus_wb)begin
			cdb_controller[0].en <= 1'b0;
			cdb_controller[1].en <= 1'b0;
			cdb_controller[0].select <= 0;
			cdb_controller[1].select <= 0;
			cdb_controller[2].en <= 1'b0;
			cdb_controller[2].select <= 0;
		end
		else begin
			if(cdb1_use)begin
				cdb_controller[0].en <= 1'b1;
				cdb_controller[0].select <= cdb_controller[0].next_select;
			end
			else begin
				cdb_controller[0].en <= 1'b0;
				cdb_controller[0].select <= 0;
			end

			if(cdb2_use)begin
				cdb_controller[1].en <= 1'b1;
				cdb_controller[1].select <= cdb_controller[1].next_select;
			end
			else begin
				cdb_controller[1].en <= 1'b0;
				cdb_controller[1].select <= 0;
			end

			if(cdb3_use)begin
				cdb_controller[2].en <= 1'b1;
				cdb_controller[2].select <= cdb_controller[2].next_select;
			end
			else begin
				cdb_controller[2].en <= 1'b0;
				cdb_controller[2].select <= 0;
			end
		end
	end
endmodule